/*
 * {comment of class}
 *
 * @author (C) <a href="http://www.carfield.com.hk">Carfield Yim </a>, 2004
 */
package hk.com.carfield.util;

import hk.com.carfield.core.Config;
import hk.com.carfield.core.Context;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

public final class UrlUtil {
	public static final Map<String, AtomicInteger> renameMap = new ConcurrentHashMap<String, AtomicInteger>();

	public static String appendParameter(final String url,
			final Map<String, String> params) {
		String str;
		if (url.indexOf("?") > 0) {
			str = url + "&amp;";
		} else {
			str = url + "?";
		}
		for (final Iterator<Map.Entry<String, String>> iter = params.entrySet()
				.iterator(); iter.hasNext();) {
			final Map.Entry<String, String> entry = iter.next();
			str += entry.getKey() + "=" + entry.getValue();
			str += "&amp;";
		}
		return str;
	}

	public static String getEncodedPath(final Config config, final File file) {
		String char1;
		try {
			char1 = URLEncoder.encode(File.separator, "UTF-8");
			final String char2 = URLEncoder.encode("/", "UTF-8");
			return URLEncoder
					.encode(UrlUtil.getRelativePath(config, file), "UTF-8")
					.replaceAll(char1, "/").replaceAll(char2, "/")
					.replaceAll("//", "/");
		} catch (final UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	public static File getLocation(final Context ctx, final String urlParam,
			final String uri) {
		try {
			String path;
			if (StringUtil.notBlank(urlParam)) {
				path = URLDecoder.decode(urlParam, "UTF-8");
			} else if (StringUtil.notBlank(ctx.config.prefix)) {
				// Also cut the '/' at first; e.g.: /index.txt
				path = URLDecoder.decode(
						uri.substring(ctx.config.prefix.length() + 1), "UTF-8");
			} else if (uri != null) {
				path = URLDecoder.decode(uri, "UTF-8");
			} else {
				path = "";
			}

			for (final String oldPath : ctx.config.nameMapping.keySet()) {
				if (path.startsWith(oldPath)) {
					LangUtil.incrementMap(UrlUtil.renameMap, path);
					final String newPath = ctx.config.nameMapping.get(oldPath);
					path = path.replace(oldPath, newPath);
					break;
				}
			}
			return ctx.config.getRoot(path);

		} catch (final UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	public static String getRelativePath(final Config config, final File file) {
		return file.getAbsolutePath()
				.substring(config.getRoot().getAbsolutePath().length())
				.replaceAll("\\\\", "/");
	}

	public static final String getUrl(final Config c, final File file) {
		return UrlUtil.getUrl(c, UrlUtil.getEncodedPath(c, file));
	}

	public static String getUrl(final Config c, final String url) {
		if (StringUtil.notBlank(c.prefix)) {
			return "/" + c.prefix + url;
		} else {
			return url;
		}
	}

	public static String getWrappedUrl(final Config config, final File f) {
		final String url = UrlUtil.getUrl(config, f);
		if (f.isDirectory()) {
			return url;
		}
		final Map<String, String> map = new HashMap<String, String>();
		map.put("wrapped", "true");
		return UrlUtil.appendParameter(url, map);
	}

	public static InputStream resolveInputStream(final Config config,
			final String name) throws IOException {
		final File file = new File(config.dataRoot, name);
		if (file.exists()) {
			return new FileInputStream(file);
		} else {
			return config.getClass().getResourceAsStream(
					"/hk/com/carfield/data/" + name);
		}
	}
}